<?php

/**
 * CFprocess is a class to simplfy processing of Databse CRUD (Create Remove Update Delete) Tables
 *
 * @package CFtable
 */

class CFprocess {

	var $maintable;
	var $fieldspec;
	
	/**
	* $newvalues
	* Array of new-pair arrays, of form:
	* $newvalues[i][<col_name>] = [value]
	* for all single transactions, i = 0.  for multiple, there is one row for each to be changed
	* rows (i) coorespond to the keys specified in $keyvalues
	*/
	var $newvalues;
	var $keyvalues;
	/**
	* $keyvalues
	* Array of new-pair arrays, of form:
	* $keyvalues[i][<col_name>] = [value]
	* for all single transactions, i = 0.  for multiple, there is one row for each to be changed
	* rows (i) coorespond to the keys specified in $newvalues
	*/	
    var $oldvalued;
	var $addtype = 'button';
	// array of mode call types, of form $mode_call_type['add']['<type>'] where <type> = s for staic, d for ajax 
	var $mode_call_types;

    var $keys;
	
    // This is the variable to use for a forced after-process page
    // not implemented yet.. just an idea
    var $ap_var;

	var $pageafteradd;
	var $pageaftersave;
	var $pageafterdelete;
	var $pageforedit = 'defuaultedit.php';
	//var $hashsalt = 'Change this default salt 0394ufw90w';

    var $actval_prefix = '';
    var $oldval_prefix = 'OV';


    var $mode_save = 'Save';
    var $mode_delete = 'Delete';
    var $mode_duplicate = 'Copy';
	
	var $mode;
	// $newvalues[<colname>] = <value>
	var $is_good = true;
	var $statusmsg = 'OK';
	
	
	
	function CFprocess($thespec = '', $listpage = 'default_list.php'){
		$this->fieldspec = $thespec;
		
		$this->pageafteradd = $listpage;
		$this->pageaftersave = $listpage;
		$this->pageafterdelete = $listpage;

		
	}

	function set_fieldspec($thespec){
		$this->fieldspec = $thespec;
	}

	function set_maintable($thetablename){
		$this->maintable = $thetablename;
	}

	
	function on_get_newvalues(){
	
	}
	
    /**
	 *
	* get_newvalues will fill the $this->newvalues with values for each past action variable ( use in adds and saves) where 
	* creates newvalues array key by column name (as defined in fieldspec) value = value from $_REQUEST
	 * $newvalues[$col_name] = value
	 */	
	function get_NV_single_static(){
		foreach($this->fieldspec AS $col_name => $colspec){
            if(isset($_REQUEST[$this->actval_prefix .$col_name])){
				$this->newvalues[0][$col_name] = urldecode($_REQUEST[$this->actval_prefix . $col_name]);
			}
		}
		$this->on_get_newvalues();
       // $this->get_keys();
	}

    /**
	 *
	 * get_keys will fill the $this->keys array with values for each key
	 * in the fieldspec, if they are defined.  Returns array foundall, with each row as true for all keys found, false if not.
	 *
	 */
	function get_KV_single_static(){
		$foundall = true;
	    foreach ($this->fieldspec as $col_name => $colspec){
	        
	        if(!empty($colspec['key'])){
	            if((isset($_REQUEST[$col_name])) AND ($_REQUEST[$col_name] != '') ){
	                $this->keyvalues[0][$col_name] = $_REQUEST[$col_name];
	                }else{
	                   $foundall = false;
	                }
	            }
			}
			return $foundall;
		}

	
	function get_params(){
	
		if(!empty($_REQUEST['seltrans'])){
		
			$goahead = $this->get_KV_multi_static();
			$this->get_NV_apply_all();
		}
		else{
		// For now, if a ajax transaction, handle it with the dynamic handler not static
			if(!empty($_REQUEST['rqkeyvalues'])){
				$this->get_NV_single_dyn();
			}
			else{
				$this->get_KV_single_static();
				$this->get_NV_single_static();
			}
		}
	
	}
	
	
    /**
	 *get_oldvalues()
	 * Set old values to values defined in request.  If a non-enpty REQUEST variable exists for the column, set value in $oldvalues[$col_name] = value
	 * in the fieldspec, if they are defined.  Returns true for all keys found, false if not.
	 *
	 */
	function get_oldvalues(){
		foreach($this->fieldspec AS $col_name => $colspec){
			if(isset($_REQUEST[$this->oldval_prefix . $col_name]) AND $_REQUEST[$this->oldval_prefix . $col_name] !== ""){
				$this->oldvalues[$col_name] = $_REQUEST[$this->oldval_prefix .$col_name];
			}
		}
		$this->on_get_oldvalues();
	}
    
	function doescape($input){
		return addslashes($input);
		}
		
    /**
	 *get_next_auto_id($column, $iskey=true)
	 * Set old values to values defined in request.  If a non-enpty REQUEST variable exists for the column, set value in $oldvalues[$col_name] = value
	 * in the fieldspec, if they are defined.  Returns true for all keys found, false if not.
	 *
	 */	
	function get_next_auto_id($column, $iskey=true){
        if (isset($this->fieldspec[$column]['source'])){
            $table = $this->fieldspec[$column]['source'];
        }else{
            $table = $this->maintable;
        }
        // NEED TO CHANGE this from 1 to the source table filter (maybe not.. ct2009-03-14)
        $next_id = get_max_value ($column, $table, 1) + 1;
        $this->newvalues[0][$column] = $next_id;
        if($iskey){
            $this->keyvalues[0][$column] = $next_id;
            }
		return $next_id;
	
	}


	
function process_ajadd(){
	if (isset($_REQUEST['rqkeyvalues'])) {
		$CV_rqkeyvalues = $_REQUEST['rqkeyvalues'];
		$CV_keyvals = explode(",", $CV_rqkeyvalues);
		$executequery = true;
		}
	else {
		$executequery = false;
	}
	
	if (isset($_REQUEST['rqkeyvariables'])) {
		$CV_rqkeyvariables = $_REQUEST['rqkeyvariables'];
		$CV_keyvars = explode(",", $CV_rqkeyvariables);
	}
	else {
		$CV_rqkeyvariables = 0;
		$executequery = false;
	}
	

	if($executequery){
		$qry_insert_new = "INSERT INTO $this->maintable ($CV_rqkeyvariables) VALUES ($CV_rqkeyvalues)";
		//print $qry_insert_new;
		$result = do_query($qry_insert_new);
		
			return $result ;
		
	} else{
		print "error";
	}
	exit;
}	
	
function get_NV_single_dyn(){
	if (isset($_REQUEST['rqkeyvalues'])) {
		$CV_rqkeyvalues = $_REQUEST['rqkeyvalues'];
		$CV_keyvals = explode(",", $CV_rqkeyvalues);
		$executequery = true;
		}
	else {
		$executequery = false;
	}
	
	if (isset($_REQUEST['rqkeyvariables'])) {
		$CV_rqkeyvariables = $_REQUEST['rqkeyvariables'];
		$CV_keyvars = explode(",", $CV_rqkeyvariables);
	}
	else {
		$CV_rqkeyvariables = 0;
		$executequery = false;
	}

	// Assign the value for each key variable into the $keyvalues array (position 0 since only one row specified)
	if($executequery){
		foreach($CV_keyvars AS $index=>$keyvar){
			$keyval = $CV_keyvals[$index];
			//print "KEYVAL=$keyval :  KEYVAR = $keyvar";
			$this->keyvalues[0][$keyvar] = $keyval;
		}
		$changecol = $_REQUEST['var'];
		$changevalue = $_REQUEST['value'];
		$this->newvalues[0][$changecol]=$changevalue;
	}
	
	// if $executequery = false, write to error variable
	}


	function get_KV_multi_static(){
		$rk_index = 0;
        $needcomma = 0;
		$dochange = false;
		if(!empty($_REQUEST['seltrans']) OR $_REQUEST['seltrans'] === 0){

			// Check for the key order, in the comma list 'rqkeyvariables'
			if (isset($_REQUEST['rqkeyvariables'])) {
				$CV_rqkeyvariables = $_REQUEST['rqkeyvariables'];
				$CV_keyvars = explode(",", $CV_rqkeyvariables);
			}
			else {
				$CV_rqkeyvariables = 0;
				$executequery = false;
			}	
			
			// produce an array ordering key variables
			foreach($CV_keyvars AS $orderindex=>$keyvar){
				$keyorder[$orderindex] = $keyvar;
			}

			// split up sets of key values and assign to 

			$ar_keyvalsets = explode(";", $_REQUEST['seltrans']);
	        foreach($ar_keyvalsets AS $setindex=>$ar_thekeyvalset){
				$ar_keyvalues = explode(",", $ar_thekeyvalset);
	            foreach($ar_keyvalues AS $keyindex=>$keyvalue){
						$keyval = $keyorder[$keyindex];
	                    $this->keyvalues[$setindex][$keyval] = $keyvalue;
	                }
	            }
	         
		} // multikey element is not empty
	
	}
	
	function get_NV_apply_all(){
		// Get count of rows to change
		$ar_keyvalsets = explode(";", $_REQUEST['seltrans']);		
		$numchangesets = count($ar_keyvalsets);
	    foreach($this->fieldspec AS $col_name => $colspec){
            if($_REQUEST['IS_CHG_' . $col_name] == 1){
				$tpl_newvalues[$col_name] = $_REQUEST[$col_name];
            }
        }
		for($counter =0; $counter < $numchangesets; $counter++){
			$this->newvalues[$counter] = $tpl_newvalues;
		}
	}
	
	
	function clean_values(){
		if(is_array($this->values)){
			foreach($this->values AS $index => $variables){
				foreach($variable AS $variable => $value){
					$this->keyvalues[$index][$variable] = addslashes($value);
				}
			}	
		}
	}
	
	function clean_keys(){
		$this->clean_values();
	}
	
	function clean_newvalues(){
		$this->clean_values();
	}
	
	function unauthorized(){
		print 'UnAuthorized';
		exit;
	}

	function authorize(){
		return true;
	}

	function get_mode(){
		$mode = $_REQUEST['mode'];
		$this->mode = $mode;
		return $mode;
	}
	
// main dispatch function	
	function do_actions(){

		$this->get_params();
		$mode = $this->get_mode();		
		
		$this->clean_keys();
		$this->clean_newvalues();
		
		if(!$this->authorize()){
			$this->unauthorized();
		}
		
		$this->on_pre_action();

	//	print "<pre>\n Mode: $mode";
	//	print "\nKeyvalues:";
	//	print_r($this->keyvalues);
	//	print "\nNewvalues:";
	//	print_r($this->newvalues);
	//	print "\n</pre>";
	//	exit;
		
		$run_mode = 'process_' . $mode;
		$pre_mode = 'on_pre_' . $mode;
		$post_mode = 'on_post_' . $mode;
		$after_mode = 'after_' . $mode;
		$error_mode = 'on_error_' . $mode;
			
		$this->on_pre_action();	
	// User define Pre Mode Action
		if(method_exists($this,$pre_mode)){
			$this->$pre_mode();
		}
	// Run Action	
		if(method_exists($this,$run_mode)){
			$this->$run_mode();
		}	
	// Handle Errors	
		if(!$this->is_good){
			if(method_exists($this,$after_mode)){
			$this->$after_mode();
			}	
		}
	// User Define Post action	
		if(method_exists($this,$post_mode)){
			$this->$post_mode();
		}


		
		if(method_exists($this,$after_mode)){
			$this->$after_mode();
		}			
	
		
	}

//---------------------------Process Functions	
	
	// Only adds one record...
	function process_New(){
        foreach($this->fieldspec AS $col_name => $colspec){
		// for input values, accept only non empty values.
            if(!empty($this->newvalues[0][$col_name]) OR $this->newvalues[0][$col_name] === '0'){
				$thisval = $this->newvalues[0][$col_name];
				//$thisval = addslashes($thisval);
				($vars=='')?$vars=$col_name:$vars.=",$col_name";
				($vals=='')?$vals = "'" . $thisval . "'":$vals .= ",'" . $thisval . "'";
				}
				// If we no data sent for this variable and it is a key, get new value
			else if(!empty($colspec['key'])){
				($vars=='')?$vars=$col_name:$vars.=",$col_name";
				($vals=='')?$vals = $this->get_next_auto_id($col_name):$vals .= "," . $this->get_next_auto_id($col_name);
				}
            }
        if($vars != ''){
            $qry_insert = "INSERT INTO $this->maintable ($vars) VALUES ($vals)";
			global $dbh;
			try{
			    /*** fetch into an PDOStatement object ***/
				$stmt = $dbh->prepare($qry_insert);

				/*** echo number of columns ***/
				$stmt->execute();
				$result =  $stmt->rowCount();
				}
			catch(PDOException $e){	
				$this->is_good = false;
				$this->statusmsg = $e->getMessage();
				}
            }	
	}	

	function process_Add(){
		$this->process_New();
	}
	
function process_Save(){
	print 'IN PSAVE';
	foreach($this->keyvalues AS $keyindex => $keys){
		//print "<br />";
		$afercomma = '';
		$afterand = '';
		foreach($keys AS $col_name => $col_value){
			//print "$col_name = $col_value <br />";
			$wherestr .= $afterand . " $col_name = '$col_value' ";
			$afterand = ' AND ';
		}
		$afercomma = '';
		foreach($this->newvalues[$keyindex] AS $val_name => $val_value){
				$setstr .= $aftercomma . " $val_name = '$val_value' ";
				$aftercomma = ',';
			}
	$qry =  "UPDATE $this->maintable SET $setstr WHERE 1=0 OR ( " . $wherestr . " )";
	print $qry;
	global $dbh;
	try{
	    /*** fetch into an PDOStatement object ***/
		$stmt = $dbh->prepare($qry);

		/*** echo number of columns ***/
		$stmt->execute();
		$result =  $stmt->rowCount();
	}
	catch(PDOException $e){	
		$this->is_good = false;
		$this->statusmsg = $e->getMessage();
	}
	$setstr = '';
	$wherestr = '';	
	}
}

function process_Multichange(){
	$this->process_Save();
}

function process_AjSave(){
	//print 'In AjSave';
	//print_r($this->newvalues);
	$this->process_Save();
}

function process_update(){
	$this->process_Save();
	
}

function process_Delete(){
	foreach($this->keyvalues AS $keyindex => $keys){
		print "<br />";
		$afercomma = '';
		$afterand = '';
		foreach($keys AS $col_name => $col_value){
			print "$col_name = $col_value <br />";
			$wherestr .= $afterand . " $col_name = '$col_value' ";
			$afterand = ' AND ';
		}

	$qry = "DELETE FROM $this->maintable WHERE 1=0 OR ( " . $wherestr . " )";
	global $dbh;
	try{
	    /*** fetch into an PDOStatement object ***/
		$stmt = $dbh->prepare($qry);

		/*** echo number of columns ***/
		$stmt->execute();
		$result =  $stmt->rowCount();
	}
	catch(PDOException $e){	
		$this->is_good = false;
		$this->statusmsg = $e->getMessage();
	}
	$wherestr = '';
	}
}

function process_Multidelete(){
	$this->process_Delete();
}

//-------------------------After Functions (Re-directs mostly)

function on_pre_action(){
}

function after_add(){
	$header_text = "Location: $this->pageafteradd";
	header($header_text); /* Redirect browser */
	}

function after_new(){
	$header_text = "Location: $this->pageafteradd";
	header($header_text); /* Redirect browser */
	}

function after_delete(){
	$header_text = "Location: $this->pageafterdelete"; 
	header($header_text); /* Redirect browser */ 
	}

function after_save(){
	$header_text = "Location: $this->pageaftersave"; 
	header($header_text); /* Redirect browser */ 
	}
function after_edit(){
	foreach($this->keyvalues[0] AS $thevar => $thevalue){
		($urlkey == '')?$urlkey = '?' . $thevar . '=' . $thevalue:$urlkey = '&' . $thevar . '=' . $thevalue;
	}
	$header_text = "Location: $this->pageforedit$urlkey"; 
	header($header_text); /* Redirect browser */ 
	}

function after_Multidelete(){	
	$header_text = "Location: $this->pageafterdelete"; 
	header($header_text); /* Redirect browser */ 
	}	


function after_AjSave(){
	if($this->is_good){
		echo 'Success';
	}
}

function after_AjNew(){
	if($this->is_good){
		echo 'Success';
	}
}


	
function after_update(){
	if($this->is_good){
		echo 'Success';
	}
}

function after_Multichange(){
	$header_text = "Location: $this->pageaftersave"; 
	header($header_text); /* Redirect browser */ 
	}	
}
?>